/*
 * EmulatedNetworkSocket.h
 *
 *  Created on: Mar 17, 2011
 *      Author: sms103
 */

#ifndef EMULATEDNETWORKSOCKET_H_
#define EMULATEDNETWORKSOCKET_H_

class EmulatedNetworkSocket;
struct network_stats;

#include <queue>
#include <pthread.h>
#include <sys/types.h>
#include <sys/time.h>
#include <stdint.h>
#include <arpa/inet.h>
#include "SFTPTransportSocket.h"
#include "../shared/ParamParser.h"
#include <stdlib.h>
#include <iostream>
#include <cmath>

//our mersenne twister random number generator
#include "MtRng.h"

using namespace std;

#define DEFAULT_NETWORK_BIT_ERROR_RATE 0
#define DEFAULT_NETWORK_DROP_RATE 0

#define NETWORK_BUFFER_SIZE 1000000
#define NETWORK_BUFFER_PACKET_LIMIT 5

struct network_stats{
	uint32_t errorsCaused;
	uint32_t packetsDropped;
	uint32_t totalBytesSent;
	uint32_t totalPacketsSent;
};

class EmulatedNetworkSocket {
public:
	EmulatedNetworkSocket(SFTPTransportSocket *sftpTranspSock, TCPSocket *tcpSock);
	virtual ~EmulatedNetworkSocket();

	bool networkSend(void *packet, size_t len);
	bool startRecvThread();

	queue<struct queue_entry *> fromNetworkDataQueue;

	void close();

	network_stats * getNetworkStats();
	void clearStats();
	double getErrorRate();

	uint32_t bufferedBytes;
	uint32_t bufferedPackets;
	ParamParser *paramParser;
	network_stats stats;

private:
	SFTPTransportSocket *transpSock;
	TCPSocket *tcpSock;
	MtRng64 mtrng;

	//needed so this layer can screw around with the bits and introduce errors without
	//permanently error'ing the packets in the transp layer's buffer
	void *packetSendBuf;

	double networkBitErrorRate;
	double networkDropRate;




	pthread_t networkRecvThread;

	//flips a bit in the specified memory region if the hasError function says there
	//should be an error in that many bits. Returns true if an error was introduced,
	//returns false otherwise
	bool causeError(uint8_t *start, uint32_t len);

	//returns true if chance says there is an error in this group of numBits bits
	//uses the networkBitErrorRate and our RNG to decide
	bool hasError(uint64_t numBits);

	//returns true if chance says the network will drop this packet.
	//uses the networkDropRate and our RNG to decide.
	bool dropThis();

	static void * runNetworkRecvThread(void *p);

	int recvPacket();

	void setParams();

};

#endif /* EMULATEDNETWORKSOCKET_H_ */
